/*
 *  Copyright (c) 2001 Sun Microsystems, Inc.  All rights
 *  reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *  1. Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *
 *  2. Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in
 *  the documentation and/or other materials provided with the
 *  distribution.
 *
 *  3. The end-user documentation included with the redistribution,
 *  if any, must include the following acknowledgment:
 *  "This product includes software developed by the
 *  Sun Microsystems, Inc. for Project JXTA."
 *  Alternately, this acknowledgment may appear in the software itself,
 *  if and wherever such third-party acknowledgments normally appear.
 *
 *  4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA"
 *  must not be used to endorse or promote products derived from this
 *  software without prior written permission. For written
 *  permission, please contact Project JXTA at http://www.jxta.org.
 *
 *  5. Products derived from this software may not be called "JXTA",
 *  nor may "JXTA" appear in their name, without prior written
 *  permission of Sun.
 *
 *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 *  ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 *  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 *  SUCH DAMAGE.
 *  ====================================================================
 *
 *  This software consists of voluntary contributions made by many
 *  individuals on behalf of Project JXTA.  For more
 *  information on Project JXTA, please see
 *  <http://www.jxta.org/>.
 *
 *  This license is based on the BSD license adopted by the Apache Foundation.
 *
 *  $Id: MenuManager.java,v 1.27 2006/07/15 23:13:58 nano Exp $
 */

package net.jxta.myjxta.ui;

import net.jxta.myjxta.View;
import net.jxta.myjxta.plugin.Plugin;
import net.jxta.myjxta.plugin.PluginAction;
import net.jxta.myjxta.plugin.PluginContainer;
import net.jxta.myjxta.ui.action.*;
import net.jxta.myjxta.util.Resources;

import javax.swing.*;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ResourceBundle;
import java.util.Set;

/**
 * @author james todd [gonzo at jxta dot org]
 * @version $Id: MenuManager.java,v 1.27 2006/07/15 23:13:58 nano Exp $
 */

public final class MenuManager {

    public static final String PLUGIN_MENU_CHAT_ONE_TO_ONE_SECURE = "MenuManager.chat.oneToOne.secure";
    private static final ResourceBundle STRINGS = Resources.getStrings();
    private View view = null;
    private final HashMap<JMenuItem, Action> g_actions = new HashMap<JMenuItem, Action>();
    
    private final HashMap<String,Action> g_pluginActions = new HashMap<String,Action>();

    private static MenuManager g_theInstance = null;

    /**
     * Singleton - only one Main-Menu Menumanager is possible
     *
     * @param p_view
     * @return the one and only instance
     */
    public static MenuManager getInstance(View p_view) {
        if (g_theInstance == null) {
            g_theInstance = new MenuManager(p_view);
        }
        return g_theInstance;
    }

    abstract class AbstractMenuListener
            implements MenuListener {
        JMenu m = null;

        AbstractMenuListener(JMenu m) {
            this.m = m;
        }

        public void menuCanceled(MenuEvent me) {
        }

        public void menuDeselected(MenuEvent me) {
        }
    }

    private MenuManager(View view) {
        this.view = view;
    }

    public JMenuBar getMenuBar() {
        JMenuBar mb = new JMenuBar();

        mb.add(buildFileMenu());
//        mb.add(getActionMenu());
//        mb.add(buildPluginsMenu());
//        mb.add(Box.createHorizontalGlue());
        mb.add(buildHelpMenu());

        return mb;
    }

    public JMenu getActionMenu() {
        return buildActionMenu();
    }

    private JMenu buildFileMenu() {
        JMenu m = new JMenu("File"/*STRINGS.getString("menu.file")*/);

        m.setMnemonic(KeyEvent.VK_F);

        m.add(buildSettingsMenu());
        m.addSeparator();
        m.add(buildQuitMenu());

        return m;
    }

    private JMenuItem buildImportMenu() {
        String l = STRINGS.getString("menu.import");

        return buildMenuItem(l, KeyEvent.VK_I,
                STRINGS.getString("tip.import"),
                new ImportAction(l, this.view));
    }

    private JMenuItem buildExportMenu() {
        String l = STRINGS.getString("menu.export");

        return buildMenuItem(l, KeyEvent.VK_E,
                STRINGS.getString("tip.export"),
                new ExportAction(l, this.view));
    }

    private JMenuItem buildSettingsMenu() {
        String l = "Settings";
        JMenuItem item;

        item = buildMenuItem(l, KeyEvent.VK_P,
                STRINGS.getString("tip.preferences"),
                new PreferencesAction(l, this.view));

        item.setEnabled(true);

        return item;
    }

    private JMenuItem buildQuitMenu() {

        String l = "Quit (Delete peer)";
        AbstractAction exitAction = new ExitAction(l, this.view.getControl());

        return buildMenuItem(l, KeyEvent.VK_E, STRINGS.getString("tip.exit"), exitAction);
    }


    private JMenu buildActionMenu() {
        JMenu m = new JMenu(STRINGS.getString("menu.action"));

        m.setMnemonic(KeyEvent.VK_A);
        m.add(buildPeersMenu());
        m.add(buildGroupsMenu());
        m.add(buildShareMenu());
//        m.add(buildImportMenu());
//        m.add(buildExportMenu());

        m.addMenuListener(new AbstractMenuListener(m) {
            public void menuSelected(MenuEvent me) {
                view.setActionMenuContext();
            }
        });

        return m;
    }

//    private JMenuItem buildPeerVoipMenu() {
//        String l = STRINGS.getString("menu.peer.voice");
//
//        return buildMenuItem(l, KeyEvent.VK_I,
//            new VoJxtaInviteAction(l, (MyJXTAView)this.view));
//    }

    /**
     * @modified 2005-04-14 jamoore add video to peers menu
     */
    private JMenu buildPeersMenu() {
        JMenu m = new JMenu(STRINGS.getString("menu.peer"));

        m.setMnemonic(KeyEvent.VK_P);

        m.add(buildPeerSearchMenu());
        m.add(buildPeerChatMenu());
//        m.add(buildPeerVoipMenu());
        m.add(buildPeerStatusMenu());
//        m.add(buildPeerProfileMenu());
//        m.add(buildPeerAddMenu());
//        m.add(buildPeerRemoveMenu());
//        m.add(buildPeerTicTacToeMenu());

        return m;
    }

    private JMenuItem buildPeerSearchMenu() {
        String l = STRINGS.getString("menu.peer.find");

        return buildMenuItem(l, KeyEvent.VK_S,
                new PeerSearchAction(l, this.view));
    }

    private class PluginActionProxy extends AbstractAction{

        private final String m_id;
	PluginActionProxy(String name,String id){
            super(name);
	    m_id=id;
        }
	public boolean isEnabled(){
	    if (g_pluginActions.get(m_id)==null)
		return false;
	    else
		return g_pluginActions.get(m_id).isEnabled();
	}
	public void actionPerformed(ActionEvent p_e) {
	    if (isEnabled())
		g_pluginActions.get(m_id).actionPerformed(p_e);
	}
    }
    private JMenuItem buildPeerChatMenu() {
        String l = STRINGS.getString("menu.peer.dialog");

        return buildMenuItem(l, KeyEvent.VK_C, ActionEvent.CTRL_MASK,
                STRINGS.getString("tip.peer.dialog"),
                new PluginActionProxy(l,PLUGIN_MENU_CHAT_ONE_TO_ONE_SECURE));
    }

    private JMenuItem buildPeerStatusMenu() {
        String l = STRINGS.getString("menu.peer.status");

        return buildMenuItem(l, KeyEvent.VK_S,
                STRINGS.getString("tip.peer.status"),
                new PeerStatusAction(l, this.view));
    }

    private JMenuItem buildPeerProfileMenu() {
        String l = STRINGS.getString("menu.peer.profile");

        return buildMenuItem(l, KeyEvent.VK_S,
                STRINGS.getString("tip.peer.profile"),
                new PeerProfileAction(l, this.view));
    }


    private JMenuItem buildPeerAddMenu() {
        String l = STRINGS.getString("menu.peer.friend.add");

        return buildMenuItem(l, KeyEvent.VK_A,
                STRINGS.getString("tip.peer.friend.add"),
                new PeerAddAction(l));
    }

    private JMenuItem buildPeerRemoveMenu() {
        String l = STRINGS.getString("menu.peer.friend.remove");

        return buildMenuItem(l, KeyEvent.VK_R,
                STRINGS.getString("tip.peer.friend.remove"),
                new PeerRemoveAction(l));
    }

    private JMenu buildGroupsMenu() {
        JMenu m = new JMenu(STRINGS.getString("menu.group"));

        m.setMnemonic(KeyEvent.VK_G);

        m.add(buildGroupSearchMenu());
        m.add(buildGroupChatMenu());
        m.add(buildGroupCreateMenu());
        m.add(buildGroupJoinMenu());
        m.add(buildGroupLeaveMenu());
        m.add(buildGroupManagementMenu());

        return m;
    }

    private JMenuItem buildGroupSearchMenu() {
        String l = STRINGS.getString("menu.group.find");

        return buildMenuItem(l, KeyEvent.VK_G,
                STRINGS.getString("tip.group.find"),
                new GroupSearchAction(l, this.view));
    }

    private JMenuItem buildGroupChatMenu() {
        String l = STRINGS.getString("menu.group.chat");

        return buildMenuItem(l, KeyEvent.VK_G,
                STRINGS.getString("tip.group.chat"),
                new GroupChatAction(l, this.view));
    }

    private JMenuItem buildGroupCreateMenu() {
        String l = STRINGS.getString("menu.group.create");;

        return buildMenuItem(l, STRINGS.getString("tip.group.create"),
                new GroupCreateAction(l, this.view, (MyJXTAView)this.view));
    }

    private JMenuItem buildGroupJoinMenu() {
        String l = STRINGS.getString("menu.group.join");

        return buildMenuItem(l, STRINGS.getString("tip.group.join"),
                new GroupJoinAction(l, this.view, (MyJXTAView)this.view));
    }

    private JMenuItem buildGroupLeaveMenu() {
        String l = STRINGS.getString("menu.group.leave");

        return buildMenuItem(l, KeyEvent.VK_L,
                STRINGS.getString("tip.group.leave"),
                new GroupResignAction(l, this.view));
    }

    private JMenuItem buildGroupManagementMenu() {
        String l = STRINGS.getString("menu.group.manage");

        return buildMenuItem(l, KeyEvent.VK_M,
                STRINGS.getString("tip.group.manage"),
                new GroupManagementAction(l, this.view));
    }

    private JMenu buildShareMenu() {
        JMenu m = new JMenu(STRINGS.getString("menu.share"));

        m.setMnemonic(KeyEvent.VK_F);

        m.add(buildShareSearchMenu());
        m.add(buildShareAddMenu());
        m.add(buildShareRemoveMenu());
        m.add(buildShareViewMenu());
        m.add(buildShareSaveMenu());
        // todo: re-enable as a plugin
        //m.add(buildBeamMenu());

        return m;
    }

    private JMenuItem buildShareSearchMenu() {
        String l = STRINGS.getString("menu.share.find");

        return buildMenuItem(l, KeyEvent.VK_F,
                STRINGS.getString("tip.share.find"),
                new ShareSearchAction(l, this.view));
    }

    private JMenuItem buildShareAddMenu() {
        String l = STRINGS.getString("menu.share.add");

        return buildMenuItem(l, KeyEvent.VK_F,
                STRINGS.getString("tip.share.add"),
                new ShareAddAction(l, this.view));
    }

    private JMenuItem buildShareRemoveMenu() {
        String l = STRINGS.getString("menu.share.remove");

        return buildMenuItem(l, KeyEvent.VK_R,
                STRINGS.getString("tip.share.remove"),
                new ShareRemoveAction(l, this.view));
    }

    private JMenuItem buildShareViewMenu() {
        String l = STRINGS.getString("menu.share.view");

        return buildMenuItem(l, KeyEvent.VK_V,
                STRINGS.getString("tip.share.view"),
                new ShareViewAction(l, this.view));
    }

    private JMenuItem buildShareSaveMenu() {
        String l = STRINGS.getString("menu.share.save");

        return buildMenuItem(l, KeyEvent.VK_S,
                STRINGS.getString("tip.share.save"),
                new ShareSaveAction(l, this.view));
    }

//    private JMenuItem buildBeamMenu() {
//        String l = "beam";
//
//        return buildMenuItem(l, KeyEvent.VK_B, "beam",
//            new BeamAction(l, (MyJXTAView)this.view));
//    }

    private JMenu buildPluginsMenu() {
        JMenu m = new JMenu(STRINGS.getString("menu.plugins"));

        m.setMnemonic(KeyEvent.VK_P);

        Plugin[] plugins = this.view.getControl().getPluginContainer().getPlugins();
        PluginContainer pluginContainer = this.view.getControl().getPluginContainer();
        for (int i = 0; i < plugins.length; i++) {
            final Plugin plugin = plugins[i];
            String name = plugin.getName();
            if (name != null) {
                JCheckBoxMenuItem pluginAction = new JCheckBoxMenuItem(new PluginAction(name, plugins[i])){
                    public boolean isSelected(){
                	return plugin.isRunning();
                    }
                };
                pluginAction.setState(plugin.isRunning());
                m.add(pluginAction);
            }
        }


        m.setEnabled(m.getMenuComponentCount() > 0);
        m.addMenuListener(new AbstractMenuListener(m) {
            public void menuSelected(MenuEvent me) {
                Component comps[]=m.getMenuComponents();
                for (int i=0;i<comps.length;i++){
                    JCheckBoxMenuItem checkBox=(JCheckBoxMenuItem) comps[i];
                    checkBox.setSelected(checkBox.isSelected());
                }
                
                
            }
        });


        return m;
    }

    private JMenu buildHelpMenu() {
        JMenu m = new JMenu("Help"/*STRINGS.getString("menu.help")*/);

        m.setMnemonic(KeyEvent.VK_H);

        m.add(buildHelpAboutProject());
        m.addSeparator();
        m.add(buildHelpAboutSoftware());

        return m;
    }

    private JMenuItem buildHelpAboutProject() {
        String l = "About project"/*STRINGS.getString("menu.about")*/;

        return buildMenuItem(l, KeyEvent.VK_A,
                STRINGS.getString("tip.about"),
                new AboutAction(l, this.view));
    }
    
    private JMenuItem buildHelpAboutSoftware() {
        String l = "About software"/*STRINGS.getString("menu.about")*/;

        return buildMenuItem(l, /*KeyEvent.VK_A,*/
                STRINGS.getString("tip.about"),
                new AboutAction(l, this.view));
    }

//    private JMenuItem buildMenuItem(String label, Action action) {
//        return buildMenuItem(label, label, action);
//    }

    private JMenuItem buildMenuItem(String label, int mnemonic,
                                    Action action) {
        return buildMenuItem(label, mnemonic, label, action);
    }

    private JMenuItem buildMenuItem(String label, String access,
                                    Action action) {
        return buildMenuItem(label, -1, access, action);
    }

    private JMenuItem buildMenuItem(String label, int mnemonic,
                                    String access, Action action) {
        return buildMenuItem(label, mnemonic, -1, access, action);
    }

    private JMenuItem buildMenuItem(String label, int mnemonic,
                                    int modifier, String access, Action action) {
        JMenuItem mi = mnemonic > -1 ?
                new JMenuItem(label, mnemonic) : new JMenuItem(label);

        mi.setText(label);

        if (mnemonic > -1 &&
                modifier > -1) {
            mi.setAccelerator(KeyStroke.getKeyStroke(mnemonic, modifier));
        }

        if (access != null) {
            mi.getAccessibleContext().setAccessibleDescription(access);
        }

        mi.setAction(action);
        g_actions.put(mi, action);

        return mi;
    }


    public void updateMenuStatus() {
        Set<JMenuItem> keys = g_actions.keySet();
        for (Iterator<JMenuItem> it = keys.iterator(); it.hasNext();) {
            Object key = it.next();
            JMenuItem jMenuItem = (JMenuItem) key;
            Action action = g_actions.get(jMenuItem);
            jMenuItem.setEnabled(action.isEnabled());
        }
    }


    public HashMap<String,Action> getPluginActionMap() {
	return g_pluginActions;
    }
}
